﻿//#pragma once


#ifndef __STRING_H__
#define __STERIG_H__

#include <iostream>
#include <cassert>
#include <cstring>
#include <algorithm>

using namespace std;

namespace yyp
{
	class string
	{
		friend ostream& operator<<(ostream& out, const string& str);

	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

		const_iterator end() const
		{
			return _str + _size;
		}

		bool operator==(const string& str) const
		{
			return 0 == strcmp((*this).c_str(), str.c_str());
		}

		bool operator!=(const string& str) const
		{
			return !(*this == str);
		}

	public:
		string(const char* s = "")
		{
			assert(s);

			if ('\0' == s[0])
			{
				_str = new char[1];
			}
			else
			{
				size_t sz = strlen(s);
				reserve(sz);

				for (size_t i = 0; i < sz;)
				{
					_str[_size++] = s[i++];
				}
			}

			_str[_size] = '\0';
			//cout << "string(const char* s = "") -- 字符串构造		" << (void*)_str << " " << _str << endl;
			cout << "string(const char* s = "") -- 字符串构造\t\t" << (void*)this << " " << "【" << (void*)_str << " " << (_str ? _str : "nullptr") << "】" << endl;
		}

		string(const string& str)
		{
			size_t sz = strlen(str._str);

			if (0 == sz)
			{
				_str = new char[1];
			}
			else
			{
				reserve(sz);

				for (size_t i = 0; i < sz;)
				{
					_str[_size++] = str._str[i++];
				}
			}
			_str[_size] = '\0';
			//cout << "string(const string& str) -- 拷贝构造		" << (void*)_str << " " << _str << endl;
			cout << "string(const string& str) -- 拷贝构造\t\t" << (void*)this << " " << "【" << (void*)_str << " " << (_str ? _str : "nullptr") << "】" << endl;
		}

		string(string&& str)
		{
			swap(str);
			//cout << "string(string&& s) -- 移动构造			" << (void*)_str << " " << _str << endl;
			cout << "string(string&& s) -- 移动构造\t\t\t" << (void*)this << " " << "【" << (void*)_str << " " << (_str ? _str : "nullptr") << "】" << endl;
		}

		~string()
		{
			//cout << "~string() -- 析构				" << (void*)_str << " " << _str << endl;
			cout << "~string() -- 析构\t\t\t\t" << (void*)this << " " << "【" << (void*)_str << " " << (_str ? _str : "nullptr") << "】" << endl;

			if (_str)
			{
				delete[] _str;
				_str = nullptr;
				_size = _capacity = 0;
			}
		}

		string& operator=(const string& str)
		{
			if (this != &str)
			{
				int sz = str.size();
				reserve(sz);

				for (size_t i = 0; i < sz; ++i)
				{
					_str[i] = str._str[i];
				}
				_size = str._size;
				_str[_size] = '\0';
			}
			//cout << "string& operator=(const string& s) -- 拷贝赋值	" << (void*)_str << " " << _str << endl;
			cout << "string& operator=(const string& s) -- 拷贝赋值\t" << (void*)this << " " << "【" << (void*)_str << " " << (_str ? _str : "nullptr") << "】" << endl;

			return *this;
		}

		string& operator=(string&& str)
		{
			swap(str);
			//cout << "string& operator=(string&& s) -- 移动赋值	" << (void*)_str << " " << _str << endl;
			cout << "string& operator=(string&& s) -- 移动赋值\t" << (void*)this << " " << "【" << (void*)_str << " " << (_str ? _str : "nullptr") << "】" << endl;

			return *this;
		}

		size_t size() const
		{
			return _size;
		}

		const char* c_str() const
		{
			return _str;
		}

		void swap(string& str)
		{
			std::swap(_str, str._str);
			std::swap(_size, str._size);
			std::swap(_capacity, str._capacity);
		}

		char& operator[](size_t pos)
		{
			assert(pos < _size);

			return _str[pos];
		}

		const char& operator[](size_t pos) const
		{
			assert(pos < _size);

			return _str[pos];
		}

		string& operator+=(char c)
		{
			push_back(c);

			return *this;
		}

		string& operator+=(const string& str)
		{
			size_t sz = str.size();
			reserve(_size + sz);

			size_t i = 0;
			while (i < sz)
			{
				_str[_size++] = str._str[i++];
			}
			_str[_size] = '\0';

			return *this;
		}

		void push_back(char c)
		{
			reserve(_size + 1);

			_str[_size++] = c;
			_str[_size] = '\0';
		}

		void reserve(size_t n = 0)
		{
			if (n > _capacity)
			{
				int newcapacity = n > 2 * _capacity ? n : 2 * _capacity;
				char* tmp = new char[newcapacity + 1];
				memcpy(tmp, _str, _size * sizeof(char));
				memset(tmp + _size, 0, (newcapacity + 1 - _size) * sizeof(char));

				delete[] _str;
				_str = tmp;
				_capacity = newcapacity;
			}
		}

		/*size_t capacity()
		{
			return _capacity;
		}*/
	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
	};

	ostream& operator<<(ostream& out, const string& str)
	{
		for (auto ch : str)
		{
			cout << ch;
		}

		return out;
	}
}

#endif